package com.twb.log.aspect;

import com.alibaba.fastjson.JSON;
import com.twb.auth.entity.twbApi.TwbApi;
import com.twb.core.base.entity.BaseLoginUser;
import com.twb.log.entity.twbLogOperation.TwbLogOperation;
import javassist.*;
import javassist.bytecode.CodeAttribute;
import javassist.bytecode.LocalVariableAttribute;
import javassist.bytecode.MethodInfo;
import org.apache.commons.lang3.StringUtils;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

public class TwbLogUtil {

    /**
     * @param ex
     * @Title log
     * @Class ExceptionInterceptor.java
     * @Description 记录日志
     * @author DSY
     * @date 2014年4月15日 下午4:23:42
     */
    public static TwbLogOperation log(TwbApi twbApi, Exception ex, boolean logEnable, BaseLoginUser loginUser, String params, Long costTime) {
        if (logEnable && null != twbApi && null != loginUser) {
            // 如果资源为空记录日志
            // 如果资源不为空，但是标明不记录日志，则不存入日志列表
            if ("0".equals(twbApi.getIslog())) {
                return null;
            }

            TwbLogOperation logOperation = new TwbLogOperation();

            // 业务操作员信息
            logOperation.setUserLoginName(loginUser.getLoginName());
            logOperation.setUserName(loginUser.getName());
            logOperation.setIp(loginUser.getIp());

            if (StringUtils.isNotBlank(twbApi.getId())) {
                // 操作内容
                logOperation.setResourceNo(twbApi.getId());
                logOperation.setLogContent(twbApi.getName());
            }

            if (ex != null) {
                // 操作失败
                logOperation.setLogResult("0");
                logOperation.setExceptionInfo(ex.getMessage() == null ? "空指针异常" : ex.getMessage());
            } else {
                // 操作成功
                logOperation.setLogResult("1");
            }

            logOperation.setUrl(twbApi.getUrl());
            logOperation.setParam(params);
            logOperation.setId(UUID.randomUUID().toString().replace("-", ""));
            logOperation.setCreator(loginUser.getLoginName());
            logOperation.setCreateDate(LocalDateTime.now());
            logOperation.setIsdel(0);
            logOperation.setCreatorId(loginUser.getId());
            logOperation.setCostTime(costTime);
            return logOperation;
        }
        return null;
    }

    /**
     * @Title getLogParam
     * @Class ExceptionInterceptor.java
     * @Description 获取本次操作提交的参数
     *
     * @param request
     * @return
     *
     * @author DSY
     * @date 2014年6月27日 下午4:31:35
     */
	/*private static String getLogParam(HttpServletRequest request) {
		Map<String, Object> map = StringUtil.mapSSToMapSO(request.getParameterMap());
		JSONObject jsonObject = new JSONObject(map);
		return jsonObject.toJSONString();
	}*/

    /**
     * @param cls
     * @param clazzName
     * @param methodName
     * @param args
     * @return
     * @throws NotFoundException
     * @Title getNameAndArgs
     * @Description 获取传入参数及参数值
     * @author DSY
     * @date 2020年10月10日 下午12:21:34
     */
    public static StringBuffer getNameAndArgs(Class<?> cls, String clazzName, String methodName, Object[] args)
            throws NotFoundException {

        if (args == null || args.length == 0) {
            return new StringBuffer("");
        }
        Map<String, Object> nameAndArgs = new HashMap<String, Object>();

        ClassPool pool = ClassPool.getDefault();
        ClassClassPath classPath = new ClassClassPath(cls);
        pool.insertClassPath(classPath);

        CtClass cc = pool.get(clazzName);
        CtMethod cm = cc.getDeclaredMethod(methodName);
        MethodInfo methodInfo = cm.getMethodInfo();
        CodeAttribute codeAttribute = methodInfo.getCodeAttribute();
        LocalVariableAttribute attr = (LocalVariableAttribute) codeAttribute.getAttribute(LocalVariableAttribute.tag);
        if (attr == null) {
            // exception
        }
        int pos = Modifier.isStatic(cm.getModifiers()) ? 0 : 1;
        for (int i = 0; i < args.length; i++) {
            Object object = args[i];
            if (object instanceof MultipartFile || object instanceof MultipartFile[] || object instanceof ServletRequest
                    || object instanceof ServletResponse || object instanceof WebDataBinder) {
                continue;
            }
            nameAndArgs.put(attr.variableName(i + pos), args[i]);// paramNames即参数名
        }
        // nameAndArgs的两种类型，用实体类接收的类似这样：
        // reqParams=com.whoareyou.fido.rest.User@616b9c0e
        // 用Map<String,Object>接收的是这样：menuNo=56473283，遍历这个map区分两种不同，使用不同的取值方式。
        // 根据获取到的值所属的不同类型通过两种不同的方法获取参数
        StringBuffer sb = new StringBuffer();
        if (nameAndArgs != null && nameAndArgs.size() > 0) {
            sb.append(JSON.toJSONString(nameAndArgs));
        }
        return sb;
    }
}
